/******************************************************************************
* Copyright (C) 2021, BBI Technology Co.,Ltd All rights reserved.
*
* Author: Embedded software group
*
* file： bsp_uart.c 
*
*
*Note：此文件位于bsp层
 ******************************************************************************/

#include "bsp_uart.h"

#ifdef RTOS 

stcATBuff AT_RXbuff;

#endif

stcUART_Idle UART_Idle;

static void Uart0_init(uint32_t baud, en_uart_mmdorck_t Parity);

void BSP_LPUART0_GPIO_Init(void)
{
	stc_gpio_cfg_t stcGpioCfg;
	DDL_ZERO_STRUCT(stcGpioCfg);
	
	Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE);	
	///<TX
	stcGpioCfg.enDir =	GpioDirOut;
	Gpio_Init(GpioPortB,GpioPin0,&stcGpioCfg);
	Gpio_SetAfMode(GpioPortB,GpioPin0,GpioAf3); //配置PB00为LPUART0_TX
	//<RX
	stcGpioCfg.enDir =	GpioDirIn;
	Gpio_Init(GpioPortB,GpioPin11,&stcGpioCfg);
	Gpio_SetAfMode(GpioPortB,GpioPin11,GpioAf3); //配置PB11为LPUART0_RX
}


void BSP_LPUART1_GPIO_Init(void)
{
	stc_gpio_cfg_t stcGpioCfg;
	DDL_ZERO_STRUCT(stcGpioCfg);

	Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE);	
	///<TX
	stcGpioCfg.enDir =	GpioDirOut;
	Gpio_Init(GpioPortB,GpioPin0,&stcGpioCfg);
	Gpio_SetAfMode(GpioPortB,GpioPin0,GpioAf3); //配置PB00为LPUART0_TX
	//<RX
	stcGpioCfg.enDir =	GpioDirIn;
	Gpio_Init(GpioPortB,GpioPin11,&stcGpioCfg);
	Gpio_SetAfMode(GpioPortB,GpioPin11,GpioAf3); //配置PB11为LPUART0_RX
}

void BSP_UART1_GPIO_Init(void)
{  
	stc_gpio_cfg_t stcGpioCfg;
	DDL_ZERO_STRUCT(stcGpioCfg);                               //初始化变量
	Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE);     //使能GPIO外设时钟门控开关
	
#if 0
	stcGpioCfg.enDir = GpioDirOut;
	Gpio_Init(GpioPortA,GpioPin4,&stcGpioCfg);
	Gpio_SetAfMode(GpioPortA,GpioPin4,GpioAf2);                //PA4 配置为UART1 TX

	stcGpioCfg.enDir = GpioDirIn;
	Gpio_Init(GpioPortA,GpioPin15,&stcGpioCfg);
	Gpio_SetAfMode(GpioPortA,GpioPin15,GpioAf2);               //PA15 配置为UART1 RX
#else
    stcGpioCfg.enDir = GpioDirOut;
    Gpio_Init(GpioPortA,GpioPin2,&stcGpioCfg);
    Gpio_SetAfMode(GpioPortA,GpioPin2,GpioAf1);             ///<配置PA02 为UART1 TX
    stcGpioCfg.enDir = GpioDirIn;
    Gpio_Init(GpioPortA,GpioPin3,&stcGpioCfg);
    Gpio_SetAfMode(GpioPortA,GpioPin3,GpioAf1);             ///<配置PA03 为UART1 RX
	
#endif
}


/******************************************************************************
PA09 -- UART0-TX
PA10 -- UART0-RX
******************************************************************************/
void BSP_UART0_GPIO_Init(void)
{  
	stc_gpio_cfg_t stcGpioCfg;
	DDL_ZERO_STRUCT(stcGpioCfg);                               //初始化变量

	Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE);	   //使能GPIO外设时钟门控开关

	stcGpioCfg.enDir = GpioDirOut;
	Gpio_Init(GpioPortA,GpioPin9,&stcGpioCfg);
	Gpio_SetAfMode(GpioPortA,GpioPin9,GpioAf1);               ///<配置PA9 为UART0 TX
	stcGpioCfg.enDir = GpioDirIn;
	Gpio_Init(GpioPortA,GpioPin10,&stcGpioCfg);
	Gpio_SetAfMode(GpioPortA,GpioPin10,GpioAf1);             ///<配置PA10 为UART0 RX
}


/**********************************************************************************************
    *函数功能:初始化UART
    *UARTx：   选择初始化UART 端口号
    *EvenOdd：奇偶校验位
    *说明IO用使用复位模式2，DMA默认是使能
 **********************************************************************************************
*/
void BSP_LPUARTx_Init(M0P_LPUART_TypeDef *LPUARTx, uint32_t baud, en_lpuart_mmdorck_t EvenOdd) 
{
	stc_lpuart_cfg_t  stcCfg;	 
    DDL_ZERO_STRUCT(stcCfg);          //结构体清零    	
	 if(LPUARTx == M0P_LPUART0)
	 {	 
	 	Sysctrl_SetPeripheralGate(SysctrlPeripheralLpUart0,TRUE); //使能外设时钟
		EnableNvic(LPUART0_IRQn, IrqLevel3, TRUE);                //系统中断使能
		BSP_LPUART0_GPIO_Init();
	 }	
	 else if(LPUARTx == M0P_LPUART1)
	 {	 	   
		Sysctrl_SetPeripheralGate(SysctrlPeripheralLpUart1,TRUE);	     
	    EnableNvic(LPUART1_IRQn, IrqLevel3, TRUE);     
	    BSP_LPUART1_GPIO_Init();
	 }  
 
#if 0	
	 stcCfg.stcBaud.enSclkSel = LPUartMskPclk;		  ///<传输时钟源:Pclk
	 stcCfg.stcBaud.u32Sclk = Sysctrl_GetPClkFreq();  ///<PCLK获取
	 
#else	/*如果需要低功耗下LPuart中断唤醒,则需要选择RCL时钟*/
	 
	 Sysctrl_SetRCLTrim(SysctrlRclFreq38400);		 ///< 配置RCL时钟为38.4kHz
	 Sysctrl_ClkSourceEnable(SysctrlClkRCL, TRUE);	 ///< 使能RCL时钟
	 stcCfg.stcBaud.enSclkSel = LPUartMskRcl;		 ///<传输时钟源:内部低速时钟
	 stcCfg.stcBaud.u32Sclk = 38400;	 
#endif	
 
	 stcCfg.enStopBit = LPUart1bit; 				  ///<1停止位	
	 stcCfg.enMmdorCk = EvenOdd; 				  	  ///<x校验  
	 stcCfg.stcBaud.enSclkDiv = LPUartMsk4Or8Div;	  ///<采样分频
	 stcCfg.stcBaud.u32Baud = baud; 				  ///<波特率
	 stcCfg.enRunMode = LPUartMskMode3; 			  ///<工作模式3
	 LPUart_Init(LPUARTx, &stcCfg); 			  
	  
	 ///<LPUART 中断使能
	 LPUart_ClrStatus(LPUARTx,LPUartRC);		  ///<清接收中断请求
	 LPUart_ClrStatus(LPUARTx,LPUartTC);		  ///<清发送中断请求
	 LPUart_EnableIrq(LPUARTx,LPUartRxIrq); 	  ///<使能接收中断
	 //LPUart_EnableIrq(LPUARTx,LPUartTxIrq);	  ///<使能发送中断	 
	 LPUart_EnableFunc(LPUARTx,LPUartDmaTxFunc);  //使能DMA发送, DMA相关通道使能后，如果Tx Buff为空，会立马启动传输		 
}    



/**********************************************************************************************
    *函数功能:初始化UART
    *UARTx：  选择初始化UART端口号
    *Parity： 奇偶校验位
    *说明IO用使用复位模式2，DMA默认是使能
 **********************************************************************************************
*/
void BSP_UARTx_Init(M0P_UART_TypeDef *UARTx, uint32_t baud, en_uart_mmdorck_t Parity) 
{
	 if(UARTx == M0P_UART0)
	 {	 	   
		Uart0_init(baud,Parity);
		EnableNvic(UART0_2_IRQn, IrqLevel3, TRUE);     ///<系统中断使能		   
	 }
	 if(UARTx == M0P_UART1)
	 {			 
		EnableNvic(UART1_3_IRQn, IrqLevel3, TRUE);	   ///<系统中断使能	
	 }	
}    


//串口0模块配置
static void Uart0_init(uint32_t baud, en_uart_mmdorck_t Parity)
{   
	stc_gpio_cfg_t stcGpioCfg;
    stc_uart_cfg_t  stcCfg;
    stc_uart_baud_t stcBaud;
	
    DDL_ZERO_STRUCT(stcGpioCfg);
    DDL_ZERO_STRUCT(stcCfg);
    DDL_ZERO_STRUCT(stcBaud);
	
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE); //GPIO外设模块时钟使能
    
    stcGpioCfg.enDir = GpioDirOut;
    Gpio_Init(GpioPortA,GpioPin9,&stcGpioCfg);
    Gpio_SetAfMode(GpioPortA,GpioPin9,GpioAf1); //配置PA09 为UART0 TX
    stcGpioCfg.enDir = GpioDirIn;
    Gpio_Init(GpioPortA,GpioPin10,&stcGpioCfg);
    Gpio_SetAfMode(GpioPortA,GpioPin10,GpioAf1);//配置PA10 为UART0 RX
 
    Sysctrl_SetPeripheralGate(SysctrlPeripheralUart0,TRUE);//UART0外设模块时钟使能
	
	stcCfg.enRunMode = UartMskMode3;     //模式3
    if(Parity == UartMskEven)
	{
		stcCfg.enMmdorCk = UartMskEven;      //偶校验
	}
	else if(Parity == UartMskOdd)
	{
		stcCfg.enMmdorCk = UartMskOdd;       //奇校验
	}
	else
	{
		stcCfg.enRunMode = UartMskMode1;     //模式1,奇偶检验无效
	}
    stcCfg.enStopBit = UartMsk1bit;      //1位停止位
    stcCfg.stcBaud.u32Baud = baud;       //波特率9600
    stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div;         //通道采样分频配置
    stcCfg.stcBaud.u32Pclk = Sysctrl_GetPClkFreq();    //获得外设时钟（PCLK）频率值
    Uart_Init(M0P_UART0, &stcCfg);       //串口初始化

    Uart_ClrStatus(M0P_UART0,UartRC);    //清接收请求
    Uart_ClrStatus(M0P_UART0,UartTC);    //清发送请求
    Uart_EnableIrq(M0P_UART0,UartRxIrq); //使能串口接收中断
    //Uart_EnableIrq(M0P_UART0,UartTxIrq); //使能串口发送中断	             
	//使能DMA发送, DMA相关通道使能后，如果Tx Buff为空，会立马启动传输
	Uart_EnableFunc(M0P_UART0,UartDmaTxFunc);  
}


void BSP_LPUARTx_SendBytes(M0P_LPUART_TypeDef* LPUARTx, uint8_t *SendBuff, uint32_t ByteLength)
{	
	for( int i = 0; i < ByteLength; i++)
	{
		LPUart_SendData(LPUARTx, SendBuff[i]);//发送数据
	}	 
}


/************************************************************************ 
 * 函数功能：串口多字节发送
 * UARTx: 端口号
 * ByteLength：长度
 * *SendBuff ：数据指针
 说明 UART_FLAG_TXE 和UART_FLAG_TC区别在于 TXE 只是移位寄存器 发出去了。不能直接进入低功耗，不然为什么出错，要么加延迟，要么TC
*************************************************************************
*/
void BSP_UARTx_SendBytes(M0P_UART_TypeDef* UARTx, uint8_t *SendBuff, uint32_t ByteLength)
{	
	for( int i = 0; i < ByteLength; i++)
	{
		Uart_SendDataPoll(UARTx, SendBuff[i]);//发送数据
	}	 
}

void BSP_UARTx_Putstr(M0P_UART_TypeDef* UARTx, char *str)
{
	while(*str)
    {   		
		Uart_SendDataPoll(UARTx, *str++);//发送数据
    } 
}

//UART0中断
//用一个定时器配合可以做idle中断
void Uart0_IRQHandler(void)
{
    if(Uart_GetStatus(M0P_UART0, UartRC))
    {
        Uart_ClrStatus(M0P_UART0, UartRC);              
        AT_RXbuff.Recv[AT_RXbuff.rx_len++] = Uart_ReceiveData(M0P_UART0);  //接收数据自动清除中断标志位	
		UART_Idle.uart_cnt = AT_RXbuff.rx_len;
		UART_Idle.timer_cnt = 0;
		Tim3_M0_Run();   //TIM3 运行
	}
	if((Uart_GetStatus(M0P_UART0, UartFE))||(Uart_GetStatus(M0P_UART0, UartPE)))  //错误请求
	{
		Uart_ClrStatus(M0P_UART0, UartFE);            //清除帧错误标记
		Uart_ClrStatus(M0P_UART0, UartPE);            //清除奇偶校验错误标记
	}
}

void Uart1_IRQHandler(void)
{



}



///<LPUART0 中断服务函数
void LpUart0_IRQHandler(void)
{  
#ifdef APP
	 BaseType_t xHigherPriorityTaskWoken = pdFALSE;	
	 uint8_t res=0;
	if(LPUart_GetStatus(M0P_LPUART0, LPUartPE))  /*奇偶检验错误*/    
    {
        LPUart_ClrStatus(M0P_LPUART0, LPUartPE);     
		
    }
    if(LPUart_GetStatus(M0P_LPUART0, LPUartRC))       ///接收数据中断
    {
        
		res =  LPUart_ReceiveData(M0P_LPUART0);
        //xQueueSendFromISR(usart_Queue,(void *) &res,&xHigherPriorityTaskWoken);
        //portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
	
    }
#else  
	
	if(LPUart_GetStatus(M0P_LPUART0, LPUartRC))       ///接收数据中断
    {
        LPUart_ClrStatus(M0P_LPUART0, LPUartRC);      ///<清接收中断请求	
			
//	 	RS485_RX_BUF[RS485_RX_CNT++] =LPUart_ReceiveData(M0P_LPUART0); 	//读取接收到的数据
//		MbRxTimeCnt=0;	
    }
	
#endif
	
	
}



void LpUart1_IRQHandler(void)
{





}


